#import "keyboard.h"

#define XKB_CTRLS_MASK (XkbAllControlsMask & ~(XkbInternalModsMask | XkbIgnoreLockModsMask))
#define MAXGROUPLENGTH 256
#define OUTPUT_LENGTH 3
#define COMPOSE_LED 5

@implementation Keyboard : Object

- (id) init {
  return [self init_w_syslog: nil];
}

- (id) init_w_syslog: (Syslog *) slog {
  if (self = [super init]) {
    XkbDescPtr kb;
    int ngroups = 0;
    int i;
    char * name = NULL;

    active = 0;
    syslog = slog;

    if (!(dpy = XOpenDisplay(0))) {
      [syslog syslog: "Cannot open display!"];
      exit(EXIT_FAILURE);
    }

    if (!(kb = XkbAllocKeyboard())) {
      [syslog syslog: "XkbAllocKeyboard"];
      exit(EXIT_FAILURE);
    }

    if (XkbGetControls(dpy, XKB_CTRLS_MASK, kb) != Success) {
      [syslog syslog: "XkbGetControls() failed."];
      exit(EXIT_FAILURE);
    }
    ngroups = kb->ctrls->num_groups;
    XkbFreeControls(kb, XKB_CTRLS_MASK, 0);

    groups = malloc(sizeof(char*)*ngroups);
    for (i = 0; i < ngroups; i++) {
      groups[i] = malloc(MAXGROUPLENGTH);
    }

    if (XkbGetNames(dpy, XkbGroupNamesMask, kb) != Success) {
      [syslog syslog: "XkbGetNames() failed"];
      exit(EXIT_FAILURE);
    }

    for (i = 0; i < ngroups; i++) {
      if (kb->names->groups[i]) {
	if ((name = XGetAtomName(dpy,
				 kb->names->groups[i]))) {
	  snprintf(groups[i], OUTPUT_LENGTH+1, name);
	} else {
	  [syslog syslog: "XgetAtomName() failed"];
	  exit(EXIT_FAILURE);
	}
      }
    }

    XkbFreeNames(kb, XkbGroupNamesMask, 0);

    XkbSelectEvents(dpy,
		    XkbUseCoreKbd,
		    XkbAllEventsMask,
		    XkbAllEventsMask);
  }
  
  return self;
}

- (char) getKbd_state {
  XkbStateRec state;

  if (XkbGetState(dpy,
		  XkbUseCoreKbd,
		  &state) != Success) {
    [syslog syslog: "XkbGetState() failed"];
    exit(EXIT_FAILURE);
  }
  active = state.group;
  
  if (!strncmp(groups[active], "USA", 3)) {
    return 1;
  }
  return 0;
}

- (void) setLed_state: (char) led_state {
  XKeyboardControl values;
  
  values.led = COMPOSE_LED;
  if (led_state) {
    values.led_mode = LedModeOn;
  } else {
    values.led_mode = LedModeOff;
  }

  XChangeKeyboardControl(dpy,
			 KBLed | KBLedMode,
			 &values);
  XSync(dpy, 0);
}

@end
